/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


/*************************************************************************
 * File: network.cpp
 *************************************************************************
 *\author: starlove
 *************************************************************************/

#include <network/network.h>
#include <zlib.h>

std::map<SOCKET, IPeer *> g_peers;

bool RegisterPeer(IPeer *pPeer)
{
	if(!pPeer)
		return false;
	g_peers.insert(std::pair<SOCKET, IPeer *>(pPeer->GetId(), pPeer));
	return true;
}

void UnRegisterPeer(IPeer *pPeer)
{
	g_peers.erase(pPeer->GetId());
}

void PACKET::Pack(LPNETWORKBUFFER p_outbuf, char *buf, unsigned int size)
{
	#ifdef __MLSE_COMPRESS_ENABLED__
	this->header.base.flag |= ePF_COMPRESS;
	#endif
    this->header.zclength = size;
    this->header.length = size + sizeof(PACKET);
    if(MASK_TEST(this->header.base.flag, ePF_COMPRESS))
    {
        if(size < __MLSE_COMPRESS_MIN_LENGTH__)
        {
            this->header.base.flag ^= ePF_COMPRESS;
        }
        else
        {
            uLongf ziped_size = ::compressBound(size);
            p_outbuf->Expand(sizeof(PACKET) + ziped_size);
            LPPACKET pPacket = (LPPACKET)p_outbuf->GetCurrPtr();
            if( ::compress((Bytef *)pPacket->GetData(), &ziped_size, (Bytef *)buf, size) == Z_OK )
            {
                memcpy(pPacket, this, sizeof(PACKET));
                pPacket->header.length = ziped_size + sizeof(PACKET);
                p_outbuf->SetOffset(pPacket->header.length);
                return;
            }
            else
            {
                this->header.base.flag ^= ePF_COMPRESS;
            }

        }
    }
    p_outbuf->Append(this, sizeof(PACKET));
    p_outbuf->Append(buf, size);
}

void PACKET::UnPack(LPNETWORKBUFFER p_outbuf)
{
    if(MASK_TEST(this->header.base.flag, ePF_COMPRESS))
    {
        uLongf ziped_size = this->header.zclength;
        p_outbuf->Expand(ziped_size);
        LPPACKET pPacket = (LPPACKET)p_outbuf->GetCurrPtr();
        if( ::uncompress((Bytef *)pPacket->GetData(), &ziped_size, (Bytef *)this->GetData(), this->header.length - sizeof(PACKET)) == Z_OK )
        {
            memcpy(pPacket, this, sizeof(PACKET));
            pPacket->header.length = ziped_size + sizeof(PACKET);
        }
        this->header.base.flag ^= ePF_COMPRESS;
        return;
    }
    p_outbuf->Append(this, this->header.length);
}
